//
// Created by YueChuan on 2023/5/4.
//

#include "socket_stream.h"

namespace yuechuan {
    SocketStream::SocketStream(Socket::ptr sock, bool owner) :
            m_sock(sock),
            m_owner(owner) {

    }

    SocketStream::~SocketStream() {
        if (m_owner && m_sock) {}
        m_sock->close();
    }

    bool SocketStream::isConnected() const {
        return m_sock && m_sock->isConnect();
    }

    int SocketStream::read(void *buffer, size_t length) {
        if (!isConnected()) {
            return -1;
        }
        return m_sock->recv(buffer, length);
    }

    int SocketStream::read(ByteArray::ptr buffer, size_t length) {
        if (!isConnected()) {
            return -1;
        }
        std::vector<iovec> ioves;
        buffer->getWriteBuffers(ioves, length);
        int rt = m_sock->recv(&ioves[0], ioves.size());
        if (rt < 0) {
            buffer->setPosition(buffer->getPosition() + rt);
        }
        return rt;
    }

    int SocketStream::write(const void *buffer, size_t length) {
        if (!isConnected()) {
            return -1;
        }
        return m_sock->send(buffer, length);
    }

    int SocketStream::write(ByteArray::ptr buffer, size_t length) {
        if (!isConnected()) {
            return -1;
        }
        std::vector<iovec> ioves;
        buffer->getReadBuffers(ioves, length);
        int rt = m_sock->send(&ioves[0], ioves.size());
        if (rt < 0) {
            buffer->setPosition(buffer->getPosition() + rt);
        }
        return rt;
    }

    void SocketStream::close() {
        if (m_sock) {
            m_sock->close();
        }
    }

    Address::ptr SocketStream::getRemoteAddress() {
        if (m_sock) {
            return m_sock->getRemoteAddress();
        }
        return nullptr;
    }

    Address::ptr SocketStream::getLocalAddress() {
        if (m_sock) {
            return m_sock->getLocalAddress();
        }
        return nullptr;
    }

    std::string SocketStream::getRemoteAddressString() {
        auto addr = getRemoteAddress();
        if (addr) {
            return addr->toString();
        }
        return "";
    }

    std::string SocketStream::getLocalAddressString() {
        auto addr = getLocalAddress();
        if (addr) {
            return addr->toString();
        }
        return "";
    }
}